package cn.supermaster.management.schedule.quartz;

import cn.supermaster.management.common.constant.ScheduleConstant;
import cn.supermaster.management.common.exception.job.TaskException;
import cn.supermaster.management.common.exception.job.TaskException.Code;
import cn.supermaster.management.schedule.domain.ScheduleTask;
import org.quartz.*;

/**
 * All rights Reserved, Designed By www.super-bytecode.com
 *
 * @ProjectName: supermaster-management
 * @Package: cn.supermaster.management.task.util
 * @ClassName: ScheduleTaskNonConcurrentExecution
 * @Description: [定时任务工具类]
 * <p> </p>
 * @Author: [Lance Ting]
 * @Date: 2021/1/13 9:10
 * @Version: V1.0
 * @Copyright: 2021 www.super-bytecode.com Inc. All rights reserved.
 * TODO: 注意,本文件Lance Ting所作,如果转载或使用请标明具体出处!
 **/
public class ScheduleTaskUtils {

    private final static String TASK_NAME = ScheduleConstant.TASK_CLASS_NAME;

    /**
     * @description: [构建任务触发对象]
     * <p></P>
     * @title: getTriggerKey
     * @author: Lance Ting
     * @date: 2021-01-13
     * @param: jobId
     * @param: jobGroup
     * @return: org.quartz.TriggerKey
     */
    public static TriggerKey getTriggerKey(Long jobId, String jobGroup) {
        String taskName = TASK_NAME + jobId;
        TriggerKey triggerKey = TriggerKey.triggerKey(taskName, jobGroup);
        return triggerKey;
    }

    /**
     * @description: [构建任务键对象]
     * <p></P>
     * @title: getJobKey
     * @author: Lance Ting
     * @date: 2021-01-13
     * @param: jobId
     * @param: jobGroup
     * @return: org.quartz.JobKey
     */
    public static JobKey getJobKey(Long jobId, String jobGroup) {
        String taskName = TASK_NAME + jobId;
        JobKey jobKey = JobKey.jobKey(taskName, jobGroup);
        return jobKey;
    }

    /**
     * @description: [创建定时任务]
     * <p></P>
     * @title: handleCronScheduleMisfirePolicy
     * @author: Lance Ting
     * @date: 2021-01-13
     * @param: scheduler
     * @param: job
     * @return: void
     * @Throws: org.quartz.SchedulerException
     * @Throws: cn.supermaster.management.common.exception.job.TaskException
     */
    public static void createScheduleJob(Scheduler scheduler, ScheduleTask job) throws SchedulerException, TaskException {
        Class<? extends Job> jobClass = getQuartzJobClass(job);
        // 构建job信息
        Long jobId = job.getJobId();
        String jobGroup = job.getJobGroup();
        String cronExpression = job.getCronExpression();
        JobKey jobKey = getJobKey(jobId, jobGroup);
        TriggerKey triggerKey = getTriggerKey(jobId, jobGroup);
        //
        JobDetail jobDetail = JobBuilder.newJob(jobClass)
                .withIdentity(jobKey)
                .build();
        // 表达式调度构建器
        CronScheduleBuilder cronScheduleBuilder = CronScheduleBuilder.cronSchedule(cronExpression);
        cronScheduleBuilder = handleCronScheduleMisfirePolicy(job, cronScheduleBuilder);
        // 按新的cronExpression表达式构建一个新的trigger
        CronTrigger trigger = TriggerBuilder.newTrigger()
                .withIdentity(triggerKey)
                .withSchedule(cronScheduleBuilder)
                .build();
        // 放入参数，运行时的方法可以获取
        jobDetail.getJobDataMap().put(ScheduleConstant.TASK_PROPERTIES, job);
        // 判断是否存在
        if (scheduler.checkExists(jobKey)) {
            // 防止创建时存在数据问题 先移除，然后在执行创建操作
            scheduler.deleteJob(jobKey);
        }
        scheduler.scheduleJob(jobDetail, trigger);
        // 暂停任务
        if (job.getStatus().equals(ScheduleConstant.Status.PAUSE.getValue())) {
            scheduler.pauseJob(ScheduleTaskUtils.getJobKey(jobId, jobGroup));
        }
    }

    /**
     * @description: [设置定时任务策略]
     * <p></P>
     * @title: handleCronScheduleMisfirePolicy
     * @author: Lance Ting
     * @date: 2021-01-13
     * @param: job
     * @param: scheduleBuilder
     * @return: org.quartz.CronScheduleBuilder
     * @Throws: cn.supermaster.management.common.exception.job.TaskException
     */
    public static CronScheduleBuilder handleCronScheduleMisfirePolicy(ScheduleTask job, CronScheduleBuilder scheduleBuilder)
            throws TaskException {
        String misfirePolicy = job.getMisfirePolicy();// 执行策略
        switch (misfirePolicy) {
            case ScheduleConstant.MISFIRE_DEFAULT:
                return scheduleBuilder;
            case ScheduleConstant.MISFIRE_IGNORE_MISFIRES:
                return scheduleBuilder.withMisfireHandlingInstructionIgnoreMisfires();
            case ScheduleConstant.MISFIRE_FIRE_AND_PROCEED:
                return scheduleBuilder.withMisfireHandlingInstructionFireAndProceed();
            case ScheduleConstant.MISFIRE_DO_NOTHING:
                return scheduleBuilder.withMisfireHandlingInstructionDoNothing();
            default:
                String message = "The task misfire policy '" + misfirePolicy
                        + "' cannot be used in cron schedule tasks";
                throw new TaskException(message, Code.CONFIG_ERROR);
        }
    }

    /**
     * @description: [获取quartz任务类]
     * <p></P>
     * @title: handleCronScheduleMisfirePolicy
     * @author: Lance Ting
     * @date: 2021-01-13
     * @param: sysJob 执行计划
     * @param: scheduleBuilder
     * @return: java.lang.Class<? extends org.quartz.Job> 具体执行任务类
     */
    private static Class<? extends Job> getQuartzJobClass(ScheduleTask scheduleTask) {
        boolean isConcurrent = "0".equals(scheduleTask.getConcurrent());
        return isConcurrent ? ScheduleTaskExecution.class : ScheduleTaskNonConcurrentExecution.class;
    }
}